/**
 * axios 封装
 * @author huangchunmao
 * @email sujinw@qq.com
 * @date 2020/5/8
*/

import Axios from 'axios'
import QS from 'qs'
import Cookies from 'js-cookie'
import Config from '@/config/axios'
import consts from '@config/const'
import { isLogin } from '@utils/login'
import { Toast } from 'vant'
const message = Toast
const instance = Axios.create({
  baseURL: consts.API_HOST,
  timeout: 6000
})

const SXH_TOKEN_NAME = 'X-Access-Token'
const UIS_TOKEN_NAME = 'X-Access-Uis-Token'

// http request 拦截器
instance.interceptors.request.use(config => {
  config.withCredentials = false
  const sxhToken = Cookies.get(consts.SXH_TOKEN)
  const uisToken = Cookies.get(consts.UIS_TOKEN)

  // 携带登录信息
  if (sxhToken) {
    config.headers[SXH_TOKEN_NAME] = sxhToken
  }
  if (uisToken) {
    config.headers[UIS_TOKEN_NAME] = uisToken
  }
  config.headers.sourceType = 'h5'

  return config
}, error => {
  // TODO 此处需要对错误返回统一处理
  return Promise.reject(error)
})

// http response 拦截器
instance.interceptors.response.use((res) => {
  // 状态码验证
  // eslint-disable-next-line no-prototype-builtins
  if (res.data && res.data.hasOwnProperty('code') && res.code !== 200) {
    if (res.config.showMessage) {
      message.success(res.data.message)
    }
    if (res.data.code === '401') {
      // 登录异常状态处理
      // message.error('登录状态失效，请重新登录！')
      const cacheURI = Cookies.get(consts.CURRENT_URI)
      const url = cacheURI || '/'
      isLogin(url)
      return false
    } else if (res.data.code !== 200) {
      console.log('发生错误', res)
      message.error(res.data.message)
    } else {
      return Promise.resolve(res.data.result)
    }
  } else {
    // TODO 业务范围异常状态处理
    if (res.config.showMessage) {
      message.success(res.data.message)
    }
  }

  // 更新TOKEN
  if (res.headers && res.headers[UIS_TOKEN_NAME]) {
    Cookies.set(consts.UIS_TOKEN, res.headers[UIS_TOKEN_NAME])
  }
  if (res.headers && res.headers[SXH_TOKEN_NAME]) {
    Cookies.set(consts.SXH_TOKEN, res.headers[SXH_TOKEN_NAME])
  }

  // 返回数据
  return Promise.resolve(res.data.result)
}, (error) => {
  const cacheURI = Cookies.get(consts.CURRENT_URI)
  const url = cacheURI || '/'
  if (error && error.response) {
    switch (error.response.status) {
      case 400:
        error.message = '请求错误'
        break
      case 401:
        error.message = '未授权，请登录'
        message.error(error.message)
        return isLogin(url, true)
      case 403:
        error.message = '拒绝访问'
        break
      case 404:
        error.message = `请求地址出错: ${error.response.config.url}`
        // location.href = '/#/404'
        break
      case 405:
        error.message = '请求方法不被允许'
        break
      case 408:
        error.message = '请求超时'
        break
      case 500:
        error.message = '服务器内部错误'
        // location.href = '/#/500'
        break
      case 501:
        error.message = '服务未实现'
        break
      case 502:
        error.message = '网关错误'
        break
      case 503:
        error.message = '服务不可用'
        break
      case 504:
        error.message = '网关超时'
        break
      case 505:
        error.message = 'HTTP版本不受支持'
        break
      default:
    }
  } else {
    error.message = error.message === 'Network Error' ? '网络错误' : error.message
  }
  // TODO 统一处理其他错误
  message.error(error.message)
  return Promise.reject(error)
})

/**
 * 接口请求公共方法
 * @param params 请求参数
 * 参数说明：
 * baseURL String 根路径
 * url String 请求路径
 * data/params Object 业务参数
 * method String 请求方法
 * responseType String 响应数据类型
 * withCredentials Boolean 是否携带cookie
 * timeout Number 超时时间(毫秒)
 * exception String 异常例外标识 skipError：跳过； download：下载
 * @param options
 * @returns {Promise<T>}
 */
export function request (params = {}, options = {}) {
  options = Object.assign({}, Config, params, options)
  if (options.contentType && options.contentType === 'application/x-www-form-urlencoded') {
    // 序列化参数为表单形式(指定数组以a[0]=b、json以a.b=d方式编码)
    options.data = QS.stringify(options.data, { arrayFormat: 'indices', allowDots: true })
  }
  return new Promise((resolve, reject) => {
    instance(options).then((response) => {
      resolve(response) // 返回数据
    }).catch((error) => {
      reject(error)
    })
  })
}

/**
 * 上传公共方法
 * @param params 参考ajax方法入参
 * @returns {Promise<any>}
 */
export function upload (params = {}, options = {}) {
  options = Object.assign({}, Config, params, options)
  options.timeout = 1000 * 60 * 60
  options.contentType = 'multipart/form-data'
  return new Promise((resolve, reject) => {
    instance(options).then((res) => {
      resolve(res)
    }).catch((error) => {
      console.warn(error)
      reject(error)
    })
  })
}

/**
 * get 请求
 * @param { String } url
 * @param { Object } params
 * @param { Object } options
 * @returns {Promise<T>}
 */
export const get = (url, params, options = {}) => {
  return request({
    url,
    params,
    method: 'GET'
  }, options)
}

/**
 * post 请求
 * @param {String} url
 * @param {Object} data
 * @param {Object} options
 * @returns {Promise<T>}
 */
export const post = (url, data = {}, options = {}) => {
  return request({
    url,
    data,
    method: 'POST'
  }, options)
}
/**
 * 供vue use使用
 */
export default {
  install (Vue) {
    Vue.prototype.$get = get
    Vue.prototype.$post = post
    Vue.prototype.$request = request
  }
}
